﻿/*************************************************************************
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using log4net;
using CatchUpTv.Utilities;
using System.Text.RegularExpressions;
using System.IO;

namespace CatchUpTv.Downloader.Rtmp
{
    /// <summary>
    /// A rtmpdump based downloader.
    /// </summary>
    public class RtmpDownloader
    {
        /// <summary>
        /// The logger for this class.
        /// </summary>
        static ILog log = LogManager.GetLogger(typeof(RtmpDownloader));

        /// <summary>
        /// The rtmp URL. Corresponds to the rtmpdump "-r" parameter.
        /// </summary>
        public string RtmpUrl { get; set; }

        /// <summary>
        /// The SWF player URL. Corresponds to the rtmpdump "-W" parameter.
        /// </summary>
        public string SwfPlayerUrl { get; set; }
        
        /// <summary>
        /// The output file. Corresponds to the rtmpdump "-o" parameter.
        /// </summary>
        public string OutputFile { get; set; }

        /// <summary>
        /// The playback path. Corresponds to the rtmpdump "-y" parameter.
        /// </summary>
        public string PlaybackPath { get; set; }

        /// <summary>
        /// The override url to the played stream. Corresponds to the rtmpdump "-t" parameter.
        /// </summary>
        public string OverrideUrl { get; set; }

        /// <summary>
        /// The rtmpdump process.
        /// </summary>
        Process _rtmpProcess;

        /// <summary>
        /// Downloads the video specified in the settings.
        /// </summary>
        /// <param name="progressListener">The progress listener.</param>
        public void DownloadVideo(Action<double, double> progressListener)
        {
            StringBuilder arguments = new StringBuilder();

            if (RtmpUrl != null)
            {
                arguments.Append(" -r ");
                arguments.Append(RtmpUrl);
            }

            if (SwfPlayerUrl != null)
            {
                arguments.Append(" -W ");
                arguments.Append(SwfPlayerUrl);
            }

            if (OutputFile != null)
            {
                arguments.Append(" -o \"");
                arguments.Append(OutputFile);
                arguments.Append("\"");
            }

            if (PlaybackPath != null)
            {
                arguments.Append(" -y ");
                arguments.Append(PlaybackPath);
            }

            if (OverrideUrl != null)
            {
                arguments.Append(" -t ");
                arguments.Append(OverrideUrl);
            }

            if (log.IsDebugEnabled)
            {
                log.Debug(arguments.ToString());
            }

            var startInfo = new ProcessStartInfo()
            {
                Arguments = arguments.ToString(),
                CreateNoWindow = true,
                FileName = "rtmpdump-win32-2.2d.exe",
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                UseShellExecute = false
            };

            _rtmpProcess = Process.Start(startInfo);

            new StreamLogger(_rtmpProcess.StandardOutput, log);
            UpdateDownloadProgress(progressListener);

            _rtmpProcess.WaitForExit();

            CheckExitCode();
        }

        /// <summary>
        /// Updates the download progress.
        /// </summary>
        /// <param name="progressListener">The progress listener.</param>
        private void UpdateDownloadProgress(Action<double, double> progressListener)
        {
            string line = _rtmpProcess.StandardError.ReadLine();

            while (line != null)
            {
                var match = ProgressRegex.Match(line);

                if (match.Success)
                {
                    string rawSize = match.Groups[1].Value;
                    string rawSizeUnit = match.Groups[2].Value;
                    string rawPercentage = match.Groups[3].Value;

                    double size = double.Parse(rawSize);
                    double percentage = double.Parse(rawPercentage);
                    
                    if (progressListener != null)
                    {
                        progressListener(percentage, size);
                    }
                }

                line = _rtmpProcess.StandardError.ReadLine();
            }
        }

        protected virtual void CheckExitCode()
        {
            if (_rtmpProcess.ExitCode == 0)
            {
                log.Info("rtmpdump reports success.");
            }
            else if (_rtmpProcess.ExitCode == 1)
            {
                log.Info("rtmpdump reports failure.");
                throw new IOException("Error downloading video");
            }
            else if (_rtmpProcess.ExitCode == 2)
            {
                log.Info("rtmpdump reports an incomplete download.");
                throw new IOException("Incomplete download");
            }
            else
            {
                log.Info("rtmpdump reported an unknown exit code: " + _rtmpProcess.ExitCode);
                throw new IOException("Unknown error");
            }
        }

        /// <summary>
        /// The regular expression to extract the progress information. E.g. "192.000 kB / 2.28 sec (0.1%)".
        /// </summary>
        private static readonly Regex ProgressRegex = new Regex(@"(\d+\.\d+)\s+(\w+) / \d+\.\d+ \w+ \((\d+\.\d+)%\)");
    }
}
